package gate

import (
	"encoding/json"
	"fmt"
	"net/url"
	"strings"
	"time"

	"gitee.com/jmesyan/mqant/conf"
	"gitee.com/jmesyan/mqant/gate"
	basegate "gitee.com/jmesyan/mqant/gate/base"
	"gitee.com/jmesyan/mqant/gate/uriRoute"
	"gitee.com/jmesyan/mqant/module"
	"gitee.com/jmesyan/mqant/selector"
	"github.com/pkg/errors"
)

var Module = func() module.Module {
	gate := new(Gate)
	return gate
}

type Gate struct {
	basegate.Gate //继承
	Route         *uriRoute.UriRoute
}

//func (this *Gate) Storage(session gate.Session) (err error) {
//	panic("implement me")
//}
//
//func (this *Gate) Delete(session gate.Session) (err error) {
//	panic("implement me")
//}
//
//func (this *Gate) Query(Userid string) (data []byte, err error) {
//	panic("implement me")
//}
//
//func (this *Gate) Heartbeat(session gate.Session) {
//	panic("implement me")
//}

func (this *Gate) GetType() string {
	//很关键,需要与配置文件中的Module配置对应
	return "Gate"
}
func (this *Gate) Version() string {
	//可以在监控时了解代码版本
	return "1.0.0"
}

func (this *Gate) OnInit(app module.App, settings *conf.ModuleSettings) {
	//注意这里一定要用 gate.Gate 而不是 module.BaseModule
	this.Route = uriRoute.NewUriRoute(this,
		uriRoute.Selector(func(topic string, u *url.URL) (s module.ServerSession, err error) {
			moduleType := u.Scheme
			nodeId := u.Hostname()
			//使用自己的
			if nodeId == "modulus" {
				//取模
			} else if nodeId == "cache" {
				//缓存
			} else if nodeId == "random" {
				//随机
			} else {
				//
				//指定节点规则就是 module://[user:pass@]nodeId/path
				//方式1
				// moduleType=fmt.Sprintf("%v@%v",moduleType,u.Hostname())
				//方式2
				return this.GetRouteServer(moduleType, selector.WithFilter(selector.FilterEndpoint(nodeId)))
			}
			return this.GetRouteServer(moduleType)
		}),
		uriRoute.DataParsing(func(topic string, u *url.URL, msg []byte) (bean interface{}, err error) {
			//根据topic解析msg为指定的结构体
			//结构体必须满足RPC的参数传递标准
			return
		}),
		uriRoute.CallTimeOut(3*time.Second),
	)

	this.Gate.OnInit(this, app, settings,
		gate.WsAddr(":3653"),
		gate.TcpAddr(":3563"),
		//gate.SetStorageHandler(this),
		//gate.SetRouteHandler(this),
		gate.ConcurrentTasks(5),
		gate.BufSize(1024),
		gate.MaxPackSize(65536),
		gate.Heartbeat(1*time.Second),
		gate.OverTime(20*time.Second),
		//gate.Tls(true),
		//gate.CertFile(""),
		//gate.KeyFile(""),
		gate.SetAgentLearner(this),
		//gate.SetSendMessageHook(func(session gate.Session, topic string, msg []byte) (bytes []byte, e error) {
		//	return nil, errors.New("本协议不允许发送给客户端")
		//}),
	)
}

//当连接建立  并且MQTT协议握手成功
func (this *Gate) Connect(agent gate.Agent) {
	//agent, err := this.GetGateHandler().GetAgent(session.GetSessionId())
	//if err != nil {
	//
	//}
	fmt.Println("agent connect", agent.ConnTime())
	//this.Gate.GetGateHandler().GetAgentNum()
	//this.Gate.GetGateHandler().GetAgent(Sessionid string) (Agent, error)
	//this.Gate.GetGateHandler().Send(span log.TraceSpan, Sessionid string, topic string, body []byte) (result interface{}, err string)
	//this.Gate.GetGateHandler().BroadCast(span log.TraceSpan, topic string, body []byte) (int64, string)

}

//当连接关闭    或者客户端主动发送MQTT DisConnect命令 ,这个函数中Session无法再继续后续的设置操作，只能读取部分配置内容了
func (this *Gate) DisConnect(agent gate.Agent) {
	fmt.Println("agent disconnect")
}

func (this *Gate) init_by_deviceid(session gate.Session, msg map[string]interface{}) (string, string) {
	return "", ""
}

func (this *Gate) OnRoute(session gate.Session, topic string, msg []byte) (bool, interface{}, error) {
	needreturn := true
	_, err := url.Parse(topic)
	if err != nil {
		return needreturn, nil, errors.Errorf("topic is not uri %v", err.Error())
	}
	if strings.HasPrefix(topic, "account://modulus/init_by_deviceid") {
		//拦截协议
		message := map[string]interface{}{}
		err := json.Unmarshal(msg, &message)
		if err != nil {
			return needreturn, "", err
		}
		r, errstr := this.init_by_deviceid(session, message)
		if errstr != "" {
			return needreturn, "", errors.Errorf(errstr)
		}
		return needreturn, r, nil
	} else {
		//利用UriRoute将消息转发至后端模块
		return this.Route.OnRoute(session, topic, msg)
	}
	return needreturn, "success", nil
}
